//======================================================================
//    We will gone,the word kept   (license)
//======================================================================
//    version & features log
// FWTF_EN/OUTREG_EN : 00=std fifo;01:std delay 1-T;
// 10=fwft mode;11=fwft too,but use outreg spcecal in bram
//====================================================================== 
//---------------------------------------
//port signals by xilinx ip;control from opensource;ram from self-code
//*************************
 module fifo
 #(parameter DATA_WIDTH = 16,
   parameter ADDR_WIDTH = 10,
   parameter PROG_EMPTY = 4,
   parameter PROG_FULL  = 2**ADDR_WIDTH-128,
   parameter FWFT_EN = "FALSE",
   parameter OUTREG_EN = "FALSE",
   parameter ASY_CLK_ENB = "TRUE")
 ( 
  input             wr_rst          ,
  input             rd_rst          ,
  input             wr_clk          ,
  input             rd_clk          ,
  input [DATA_WIDTH-1:0]    din             ,
  input                     wr_en           ,
  input                     rd_en           ,
  output [DATA_WIDTH-1:0]   dout            ,
  output                    full            ,
  output                    empty           ,
  output [ADDR_WIDTH:0]     rd_data_count   ,
  output [ADDR_WIDTH:0]     wr_data_count   ,
  output                    almost_empty    ,
  output            almost_full     
 );

wire           val_wr  ;   
wire[ADDR_WIDTH-1:0]   wraddr  ;   
wire           val_rd  ;   
wire           val_regceb ;
wire[ADDR_WIDTH-1:0]   rdaddr  ;  
wire           rst     ;
assign rst = wr_rst | rd_rst ;//simple 

generate
if (ASY_CLK_ENB == "TRUE") 
    asfifo_task   #(
        .ADDR_WIDTH      (ADDR_WIDTH       ),
        .PROG_EMPTY_OFST (PROG_EMPTY ),
        .PROG_FULL_OFST  (PROG_FULL  ),
        .FWFT_EN         (FWFT_EN    ),
        .OUTREG_EN       (OUTREG_EN  )
      )  u_asfifo_task(
      	.rst          (rst           ),
        .wr_clk_i     (wr_clk        ),
        .wr_en_i      (wr_en         ),
        .wr_cnt       (wr_data_count ),
        .full_o       (full       ),
        .prog_full_o  (almost_full  ),
        .rd_clk_i     (rd_clk     ),
        .rd_en_i      (rd_en ),
        .rd_cnt       (rd_data_count ),
        .empty_o      (empty      ),
        .prog_empty_o (almost_empty  ),
        .val_wr       (val_wr       ),
        .wraddr       (wraddr       ),
        .val_rd       (val_rd       ),
        .val_regceb   (val_regceb   ),
        .rdaddr       (rdaddr       )
      );
else begin
    sfifo_task   #(
        .ADDR_WIDTH      (ADDR_WIDTH       ),
    //    .DATA_WIDTH      (DATA_WIDTH       ),
        .PROG_EMPTY_OFST (PROG_EMPTY ),
        .PROG_FULL_OFST  (PROG_FULL  ),
        .FWFT_EN         (FWFT_EN    ),
        .OUTREG_EN       (OUTREG_EN  )
      )  u_fifo_task(
      	.clk        (rd_clk        )   ,
        .rst        (rst        )   ,
        .wr_en_i    (wr_en      )   ,
        .rd_en_i    (rd_en       )  ,
        .prog_empty (almost_empty ) ,
        .prog_full  (almost_full  ) ,
        .full_o     (full       )   ,
        .empty_o    (empty )        ,
        .data_count (rd_data_count)    ,
        //
        .val_wr     (val_wr     )   ,
        .val_rd     (val_rd     )   ,
        .val_regceb (val_regceb )   ,
        .rdaddr     (rdaddr     )   ,
        .wraddr     (wraddr     )
      );
      assign wr_data_count = rd_data_count ;
end
endgenerate

//ip ram decided by dpram1w1r.v
dpram1w1r #(
	.RAM_WIDTH (DATA_WIDTH),
	.RAM_DEPTH (2**ADDR_WIDTH),
  .OUTREG_EN (OUTREG_EN) 
	) u_ram
	(
		.clka       (wr_clk ) ,
		.wea	      (val_wr ) ,
		.addra      (wraddr ) ,
		.dina       (din )    ,
		.clkb       (rd_clk ) ,
		.enb	      (val_rd ),
    .regceb     (val_regceb ),
		.addrb      (rdaddr ) ,
		.doutb      (dout ) 
		);
 endmodule